package com.wehealth.three.lib_connect.device.bluetoothdevice;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import androidx.annotation.RequiresApi;


import com.wehealth.three.lib_connect.R;
import com.wehealth.three.lib_connect.device.usbdevice.data.ParseOriginEcgData;

import com.wehealth.three.lib_connect.utils.AppGlobals;
import com.wehealth.three.lib_connect.utils.ByteDataUtil;
import com.wehealth.three.lib_connect.utils.DateUtil;
import com.wehealth.three.lib_connect.utils.PreferenceUtils;
import com.wehealth.three.lib_connect.utils.SaveLogUtil;

import java.util.Date;
import java.util.UUID;

/****
 * ble蓝牙发送指令获取心电数据
 */
public class BleConnectThread extends Thread {//

    protected final int DRAW_ECG_WAVE = 1000;
    protected final int BT_CONNECT_DEVICE_ERROR = 899;
    protected final int DISMISS_PROGRESS_DIALOG = 801;
    protected final int SHOW_PROGRESS_DIALOG = 800;
    protected final int BT_CONNECT_FAILED = 997;

    private BluetoothGatt mBleGatt;
    private BluetoothGattCharacteristic bleWriteCharacteristic;
    private BluetoothDevice bluetoothDevice;
    private Handler handler;
    private Context context;
    private BleDataListener bleDataListener;

    private boolean[] leadState = new boolean[10];
    private String leadStr = "";
    private int gain = 1;
    private int[][] tempBLEBuf = new int[8][16];
    private StringBuffer sbByte = new StringBuffer();

    private boolean bleSNCount;
    private boolean startReceive = false;//开始接收数据为true,否则为false;
    private int lastNum = -1;
    private int bleOneReceive = 0;

    public BleConnectThread(Context ctx, BluetoothDevice bluetoothDevice, Handler h, BleDataListener bdListener) {
        handler = h;
        context = ctx;
        bleDataListener = bdListener;
        this.bluetoothDevice = bluetoothDevice;
    }

    BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
        @SuppressLint("MissingPermission")
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            switch (newState) {
                case BluetoothProfile.STATE_CONNECTING:
                    Message msg = handler.obtainMessage(SHOW_PROGRESS_DIALOG);
                    msg.obj =AppGlobals.INSTANCE.get().getResources().getString(R.string.ble_connecting);
                    handler.sendMessage(msg);
                    break;
                case BluetoothProfile.STATE_CONNECTED:
                    gatt.discoverServices();
                    PreferenceUtils.getInstance().setDeviceBluetoothType(false);
                    handler.sendEmptyMessage(DRAW_ECG_WAVE);
                    handler.sendEmptyMessage(DISMISS_PROGRESS_DIALOG);
                    break;
                case BluetoothProfile.STATE_DISCONNECTED:
                    Log.e("TAG", "蓝牙断开");
                    msg = handler.obtainMessage(BT_CONNECT_DEVICE_ERROR);
                    msg.obj = AppGlobals.INSTANCE.get().getResources().getString(R.string.ble_bt_broken);
                    handler.sendMessage(msg);
                    break;
                case BluetoothProfile.STATE_DISCONNECTING:
                    Log.e("TAG", "蓝牙正在断开...");
                    handler.sendEmptyMessage(SHOW_PROGRESS_DIALOG);
                    break;
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            BluetoothGattService gattService = gatt.getService(UUID.fromString("974CBE30-3E83-465E-ACDE-6F92FE712134"));// 获取到服务的通道
            //获取到Notify的Characteristic通道 这个根据协议来定  如果设备厂家给的协议不是Notify的话  就不用做以下操作了
            BluetoothGattCharacteristic notifyCharacteristic = gattService.getCharacteristic(UUID.fromString("974CBE31-3E83-465E-ACDE-6F92FE712134"));
            @SuppressLint("MissingPermission")
            boolean ding = gatt.setCharacteristicNotification(notifyCharacteristic, true);
            enableNotification(gatt, ding, notifyCharacteristic);
            bleWriteCharacteristic = gattService.getCharacteristic(UUID.fromString("974CBE32-3E83-465E-ACDE-6F92FE712134"));
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
        }

        @RequiresApi(api = Build.VERSION_CODES.O)
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            byte[] va = characteristic.getValue();//得到原始数据

            sbByte.append(ByteDataUtil.toHex(va, " ")).append("\n");
            int sn = Byte.toUnsignedInt(va[1]);
            if (bleSNCount) {
                Log.e("TAG", "序列号：" + sn);
                if (lastNum + 1 != sn) {//有数据丢失
                    Log.e("TAG", "丢失后的序列号：" + sn + " 丢失前得序列号：" + lastNum);
                    bleSNCount = false;
//                    handler.sendEmptyMessage(BLE_RECONNECT);
                    startReceive = false;
                    bleOneReceive = 0;
                    lastNum = sn;
                    clearBuffer();
                    return;
                }
                if (lastNum == 254) {
                    lastNum = -1;
                } else {
                    lastNum++;
                }
            } else {
                bleSNCount = true;
                lastNum = sn;
            }
            if (!startReceive) {//判断开始接收数据
                if (va[0] == (byte) 0xE0 || va[0] == (byte) 0xE8) {//从E0或者E8开始接收
                    startReceive = true;
                } else {
                    return;
                }
            }
            if (va[0] == (byte) 0xC1) {
                leadState = ByteDataUtil.bleParseLeadState(va);
                leadStr = ByteDataUtil.toHex(new byte[]{va[7], va[8]}, " ");
                gain = ByteDataUtil.bleParseGain(va);
            } else {
                processArray(va);
                bleOneReceive++;
                int length = va[0] >= (byte) 0xE8 ? 16 : 6;
                if (bleOneReceive == 8) {
                    for (int i = 0; i < length; i++) {//循环6次，从队列里取出数据，然后在处理
                        int[] tempBuf = new int[8];
                        tempBuf[0] = tempBLEBuf[0][i];
                        tempBuf[1] = tempBLEBuf[1][i];
                        tempBuf[2] = tempBLEBuf[2][i];
                        tempBuf[3] = tempBLEBuf[3][i];
                        tempBuf[4] = tempBLEBuf[4][i];
                        tempBuf[5] = tempBLEBuf[5][i];
                        tempBuf[6] = tempBLEBuf[6][i];
                        tempBuf[7] = tempBLEBuf[7][i];
                        switchECGData(tempBuf);
                    }
                    bleOneReceive = 0;
                }
            }
        }

        @RequiresApi(api = Build.VERSION_CODES.O)
        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
            startBleData();
        }
    };

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void processArray(byte[] va) {
        Log.w("processArray", "processArray：" + ByteDataUtil.toHex(va, " "));
        if (va[0] >= (byte) 0xE8) {//解析压缩后的数据包
            if (va[0] == (byte) 0xE8) {//压缩后的第一通道
                int[] d = ByteDataUtil.bleParsePackECG2(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[0], 0, d.length);
            }
            if (va[0] == (byte) 0xE9) {
                int[] d = ByteDataUtil.bleParsePackECG2(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[1], 0, d.length);
            }
            if (va[0] == (byte) 0xEA) {
                int[] d = ByteDataUtil.bleParsePackECG2(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[2], 0, d.length);
            }
            if (va[0] == (byte) 0xEB) {
                int[] d = ByteDataUtil.bleParsePackECG2(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[3], 0, d.length);
            }
            if (va[0] == (byte) 0xEC) {
                int[] d = ByteDataUtil.bleParsePackECG2(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[4], 0, d.length);
            }
            if (va[0] == (byte) 0xED) {
                int[] d = ByteDataUtil.bleParsePackECG2(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[5], 0, d.length);
            }
            if (va[0] == (byte) 0xEE) {
                int[] d = ByteDataUtil.bleParsePackECG2(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[6], 0, d.length);
            }
            if (va[0] == (byte) 0xEF) {
                int[] d = ByteDataUtil.bleParsePackECG2(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[7], 0, d.length);
            }
        } else {//解析未压缩得数据包
            if (va[0] == (byte) 0xE0) {//第一通道的数据
                int[] d = ByteDataUtil.bleParsePackECG(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[0], 0, d.length);
            }
            if (va[0] == (byte) 0xE1) {
                int[] d = ByteDataUtil.bleParsePackECG(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[1], 0, d.length);
            }
            if (va[0] == (byte) 0xE2) {
                int[] d = ByteDataUtil.bleParsePackECG(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[2], 0, d.length);
            }
            if (va[0] == (byte) 0xE3) {
                int[] d = ByteDataUtil.bleParsePackECG(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[3], 0, d.length);
            }
            if (va[0] == (byte) 0xE4) {
                int[] d = ByteDataUtil.bleParsePackECG(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[4], 0, d.length);
            }
            if (va[0] == (byte) 0xE5) {
                int[] d = ByteDataUtil.bleParsePackECG(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[5], 0, d.length);
            }
            if (va[0] == (byte) 0xE6) {
                int[] d = ByteDataUtil.bleParsePackECG(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[6], 0, d.length);
            }
            if (va[0] == (byte) 0xE7) {
                int[] d = ByteDataUtil.bleParsePackECG(va);
                //存入二维数组
                System.arraycopy(d, 0, tempBLEBuf[7], 0, d.length);
            }
        }
    }

    //转换数据，将八个点换算成12个点
    private void switchECGData(int[] ecgData) {
        int[] ed = new int[ecgData.length];
        for (int i = 0; i < ecgData.length; i++) {
            double edd = (ecgData[i] * 6 / gain) * 10.486;
            ed[i] = (int) edd;
        }
        int[] ecgDataReal = new int[12];
        ecgDataReal[0] = ed[0];
        ecgDataReal[1] = ed[1];
        ecgDataReal[2] = (ed[1] - ed[0]); // III II - I
        ecgDataReal[3] = (-((ed[1] + ed[0]) >> 1)); // avR
        ecgDataReal[4] = (ed[0] - (ed[1] >> 1)); // avL
        ecgDataReal[5] = (ed[1] - (ed[0] >> 1)); // avF
        for (int k = 2; k < 8; k++) {
            ecgDataReal[k + 4] = ed[k];
        }
        boolean[] leadStateReal = new boolean[leadState.length];
        System.arraycopy(leadState, 0, leadStateReal, 0, leadState.length);
        String lead = leadStr;
        bleDataListener.getBleEcgData(ecgDataReal, leadStateReal, lead);//通过接口返回到绘图页面
    }

    @SuppressLint("MissingPermission")
    private void enableNotification(BluetoothGatt bluetoothGatt, boolean enable, BluetoothGattCharacteristic characteristic) {
        if (bluetoothGatt == null || characteristic == null) {
            return;
        }
        if (!bluetoothGatt.setCharacteristicNotification(characteristic, enable)) {
            return;
        }
        //获取到Notify当中的Descriptor通道  然后再进行注册
        BluetoothGattDescriptor clientConfig = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
        if (clientConfig == null) {
            return;
        }
        if (enable) {
            clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        } else {
            clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
        }
        bluetoothGatt.writeDescriptor(clientConfig);
    }

    @SuppressLint("MissingPermission")
    private void startBleData() {
        if (bleWriteCharacteristic != null) {
            bleWriteCharacteristic.setValue(ParseOriginEcgData.packEcgDeviceStart());
        }
        Log.e("TAG", "startBleData  setValue(start) 特征值设置开始命令");
        try {
            if (mBleGatt != null && mBleGatt.connect()) {
                boolean result = mBleGatt.writeCharacteristic(bleWriteCharacteristic);
                Log.e("TAG", "startBleData 0 write(start): " + result + "  往蓝牙连接写入开始命令 第一次");
            }
        } catch (Exception e) {
            e.printStackTrace();
            Message msg = handler.obtainMessage(BT_CONNECT_FAILED);
            msg.obj = AppGlobals.INSTANCE.get().getResources().getString(R.string.ble_bt_broken);
            handler.sendMessage(msg);
        }
    }

    private void clearBuffer() {
        tempBLEBuf = new int[8][16];
        sbByte.delete(0, sbByte.length());
    }

    @SuppressLint("MissingPermission")
    public void stopBleData() {//停止调用，保存数据
        if (bleWriteCharacteristic != null) {//发送停止命令
            bleWriteCharacteristic.setValue(ParseOriginEcgData.packEcgDeviceStop());
            if (mBleGatt != null && mBleGatt.connect()) {//将命令写入特征值
                boolean writeState = mBleGatt.writeCharacteristic(bleWriteCharacteristic);
                if (!writeState) {
                    mBleGatt.writeCharacteristic(bleWriteCharacteristic);
                }
                mBleGatt.disconnect();
                mBleGatt.close();
                Log.e("TAG", "关闭连接  mBleGatt.close()");
            }
        }
        String time = DateUtil.sdf_yyyyMMddHHmmss.format(new Date());
        if (sbByte.length() > 0) {
            SaveLogUtil.saveBytes(context, time, sbByte.toString());
            sbByte.delete(0, sbByte.length());
        }
    }

    @SuppressLint("MissingPermission")
    private void connectBleDevice() {
        tempBLEBuf = new int[8][16];
        Message msg = handler.obtainMessage(SHOW_PROGRESS_DIALOG);
        msg.obj = AppGlobals.INSTANCE.get().getResources().getString(R.string.ble_connecting);
        handler.sendMessage(msg);
        startReceive = false;
        mBleGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback);
    }


    @SuppressLint("MissingPermission")
    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public void run() {
        if (bluetoothDevice!=null){
            connectBleDevice();
        }
    }
}
